<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AI对话助手</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#165DFF',
                        secondary: '#0A2463',
                        neutral: '#F5F7FA',
                        'neutral-dark': '#E5E6EB',
                        'text-primary': '#1D2129',
                        'text-secondary': '#4E5969',
                        'text-tertiary': '#86909C'
                    },
                    fontFamily: {
                        inter: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .scrollbar-hide {
                -ms-overflow-style: none;
                scrollbar-width: none;
            }
            .scrollbar-hide::-webkit-scrollbar {
                display: none;
            }
            .typing-animation::after {
                content: '|';
                animation: typing 1s infinite;
            }
            @keyframes typing {
                0%, 100% { opacity: 1; }
                50% { opacity: 0; }
            }
            .chat-hover {
                @apply transition-all duration-200 hover:bg-primary/5;
            }
            .chat-active {
                @apply bg-primary/10 font-medium;
            }
        }
    </style>
</head>
<body class="font-inter bg-neutral min-h-screen flex flex-col">
<div class="flex flex-grow overflow-hidden">
    <!-- 左侧聊天列表 -->
    <div id="chat-list-container" class="w-64 bg-white border-r border-neutral-dark flex-shrink-0 flex flex-col transition-all duration-300">
        <div class="p-4 border-b border-neutral-dark">
            <button id="new-chat-btn" class="w-full bg-primary hover:bg-primary/90 text-white py-2 rounded-lg flex items-center justify-center gap-2 transition-all transform hover:scale-[1.02]">
                <i class="fa fa-plus"></i>
                <span>新建聊天</span>
            </button>
        </div>

        <div id="chat-list" class="flex-grow overflow-y-auto scrollbar-hide p-2">
            <div class="chat-item chat-active cursor-pointer p-3 rounded-lg mb-1 flex items-center justify-between" data-id="chat-1">
                <div class="flex items-center gap-2">
                    <i class="fa fa-comment-dots text-primary"></i>
                    <span class="truncate">聊天 1</span>
                </div>
                <div class="flex gap-1 opacity-0 hover:opacity-100 transition-opacity">
                    <button class="edit-chat-btn p-1 text-text-tertiary hover:text-primary">
                        <i class="fa fa-pencil"></i>
                    </button>
                    <button class="delete-chat-btn p-1 text-text-tertiary hover:text-red-500">
                        <i class="fa fa-trash"></i>
                    </button>
                </div>
            </div>
        </div>
    </div>

    <!-- 右侧聊天内容 -->
    <div class="flex-grow flex flex-col">
        <div class="bg-white border-b border-neutral-dark p-4 shadow-sm">
            <h2 id="current-chat-title" class="text-lg font-semibold text-text-primary">聊天 1</h2>
        </div>

        <div id="chat-container" class="flex-grow overflow-y-auto p-4 bg-neutral">
            <div class="flex items-start mb-6 animate-fade-in">
                <div class="flex-shrink-0 mr-3">
                    <div class="h-10 w-10 rounded-full bg-primary flex items-center justify-center text-white">
                        <i class="fa fa-robot"></i>
                    </div>
                </div>
                <div class="bg-white p-4 rounded-lg rounded-tl-none max-w-[90%] shadow-sm">
                    <p class="text-text-primary">你好！我是AI助手，有什么可以帮助你的吗？</p>
                </div>
            </div>
        </div>

        <div class="bg-white border-t border-neutral-dark p-4">
            <form id="message-form" class="relative">
                <div class="flex flex-col md:flex-row gap-3">
                    <div class="flex-grow relative">
                        <textarea id="user-input" rows="3" placeholder="请输入你的问题..." class="w-full px-4 py-3 rounded-lg border border-neutral-dark focus:border-primary focus:ring-2 focus:ring-primary/20 transition-all resize-none outline-none bg-white shadow-sm"></textarea>
                        <div class="absolute bottom-2 right-2 text-xs text-text-tertiary">
                            <span id="char-count">0</span>/2000
                        </div>
                    </div>
                    <button type="submit" id="send-button" class="bg-primary hover:bg-primary/90 text-white font-medium px-6 py-3 rounded-lg shadow-md transition-all transform hover:scale-105 active:scale-95 flex items-center justify-center">
                        <i class="fa fa-paper-plane mr-2"></i>
                        <span>发送</span>
                    </button>
                </div>
                <div id="model-selector" class="mt-3 flex flex-wrap gap-2">
                    <label class="text-sm text-text-secondary">选择模型:</label>
                    <select id="model" class="bg-white border border-neutral-dark rounded-md px-3 py-1 text-sm focus:outline-none focus:ring-1 focus:ring-primary focus:border-primary">
                        <option value="deepseek-r1:1.5b">deepseek-r1:1.5b</option>
                        <option value="llama3:7b">llama3:7b</option>
                        <option value="mistral:7b">mistral:7b</option>
                    </select>
                </div>
            </form>
        </div>
    </div>
</div>

<!-- 重命名聊天对话框 -->
<div id="rename-modal" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 hidden">
    <div class="bg-white rounded-lg p-6 w-full max-w-md shadow-xl transform transition-all">
        <h3 class="text-lg font-semibold mb-4">重命名聊天</h3>
        <input type="text" id="rename-input" class="w-full px-4 py-2 border border-neutral-dark rounded-lg mb-4 focus:outline-none focus:ring-1 focus:ring-primary focus:border-primary" placeholder="请输入新名称">
        <div class="flex justify-end gap-3">
            <button id="cancel-rename" class="px-4 py-2 border border-neutral-dark rounded-lg hover:bg-neutral transition-colors">取消</button>
            <button id="confirm-rename" class="px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors">确认</button>
        </div>
    </div>
</div>

<script>
    document.addEventListener('DOMContentLoaded', () => {
        // 状态管理
        let chats = [
            { id: 'chat-1', title: '聊天 1', messages: [] }
        ];
        let currentChatId = 'chat-1';
        let eventSource = null;
        let currentAiMessageElement = null;
        let isStreaming = false;
        let editingChatId = null;

        // DOM元素
        const chatListContainer = document.getElementById('chat-list-container');
        const chatList = document.getElementById('chat-list');
        const newChatBtn = document.getElementById('new-chat-btn');
        const chatContainer = document.getElementById('chat-container');
        const messageForm = document.getElementById('message-form');
        const userInput = document.getElementById('user-input');
        const sendButton = document.getElementById('send-button');
        const charCount = document.getElementById('char-count');
        const modelSelect = document.getElementById('model');
        const currentChatTitle = document.getElementById('current-chat-title');
        const renameModal = document.getElementById('rename-modal');
        const renameInput = document.getElementById('rename-input');
        const cancelRenameBtn = document.getElementById('cancel-rename');
        const confirmRenameBtn = document.getElementById('confirm-rename');

        // 初始化聊天列表
        renderChatList();

        // 更新字符计数
        userInput.addEventListener('input', () => {
            const count = userInput.value.length;
            charCount.textContent = count;

            if (count > 2000) {
                charCount.classList.add('text-red-500');
                userInput.value = userInput.value.substring(0, 2000);
                charCount.textContent = 2000;
            } else {
                charCount.classList.remove('text-red-500');
            }
        });

        // 提交表单
        messageForm.addEventListener('submit', (e) => {
            e.preventDefault();
            sendMessage();
        });

        // 按Enter发送消息（Shift+Enter换行）
        userInput.addEventListener('keydown', (e) => {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                sendMessage();
            }
        });

        // 新建聊天
        newChatBtn.addEventListener('click', () => {
            const newChatId = `chat-${Date.now()}`;
            const newChat = {
                id: newChatId,
                title: `新聊天 ${chats.length + 1}`,
                messages: []
            };

            chats.push(newChat);
            currentChatId = newChatId;
            renderChatList();
            updateCurrentChatTitle();
            clearChatContainer();
        });

        // 取消重命名
        cancelRenameBtn.addEventListener('click', () => {
            renameModal.classList.add('hidden');
            editingChatId = null;
        });

        // 确认重命名
        confirmRenameBtn.addEventListener('click', () => {
            const newTitle = renameInput.value.trim();
            if (newTitle && editingChatId) {
                const chat = chats.find(c => c.id === editingChatId);
                if (chat) {
                    chat.title = newTitle;
                    if (editingChatId === currentChatId) {
                        updateCurrentChatTitle();
                    }
                    renderChatList();
                }
            }
            renameModal.classList.add('hidden');
            editingChatId = null;
        });

        // 发送消息
        function sendMessage() {
            const message = userInput.value.trim();
            const model = modelSelect.value;

            if (message === '' || isStreaming) return;

            // 添加用户消息到对话
            appendUserMessage(message);

            // 将消息添加到当前聊天
            addMessageToChat('user', message);

            // 清空输入框
            userInput.value = '';
            charCount.textContent = '0';

            // 添加AI正在输入的状态
            appendAiTyping();

            // 发送请求
            fetchStreamingResponse(message, model);
        }

        // 添加用户消息到对话
        function appendUserMessage(message) {
            const userMessageHtml = `
                    <div class="flex items-start justify-end mb-6 animate-fade-in">
                        <div class="bg-primary/10 p-4 rounded-lg rounded-tr-none max-w-[90%]">
                            <p class="text-text-primary">${escapeHtml(message)}</p>
                        </div>
                        <div class="flex-shrink-0 ml-3">
                            <div class="h-10 w-10 rounded-full bg-gray-200 flex items-center justify-center">
                                <i class="fa fa-user text-gray-500"></i>
                            </div>
                        </div>
                    </div>
                `;

            chatContainer.insertAdjacentHTML('beforeend', userMessageHtml);
            scrollToBottom();
        }

        // 添加AI正在输入的状态
        function appendAiTyping() {
            // 移除之前的"正在输入"状态
            const oldTypingElement = document.getElementById('ai-typing');
            if (oldTypingElement) {
                oldTypingElement.remove();
            }

            const aiTypingHtml = `
                    <div id="ai-typing" class="flex items-start mb-6 opacity-0 transition-opacity duration-300">
                        <div class="flex-shrink-0 mr-3">
                            <div class="h-10 w-10 rounded-full bg-primary flex items-center justify-center text-white">
                                <i class="fa fa-robot"></i>
                            </div>
                        </div>
                        <div class="bg-white p-4 rounded-lg rounded-tl-none max-w-[90%] shadow-sm">
                            <p class="text-text-primary typing-animation">思考中</p>
                        </div>
                    </div>
                `;

            chatContainer.insertAdjacentHTML('beforeend', aiTypingHtml);

            // 淡入动画
            setTimeout(() => {
                document.getElementById('ai-typing').classList.remove('opacity-0');
            }, 10);

            scrollToBottom();

            // 创建AI消息元素并添加唯一标识
            const messageId = `ai-response-${Date.now()}`;
            currentAiMessageElement = document.createElement('div');
            currentAiMessageElement.id = messageId;
            currentAiMessageElement.className = 'flex items-start mb-6 opacity-0 transition-opacity duration-300';
            currentAiMessageElement.innerHTML = `
                    <div class="flex-shrink-0 mr-3">
                        <div class="h-10 w-10 rounded-full bg-primary flex items-center justify-center text-white">
                            <i class="fa fa-robot"></i>
                        </div>
                    </div>
                    <div class="bg-white p-4 rounded-lg rounded-tl-none max-w-[90%] shadow-sm">
                        <p id="ai-response-${messageId}" class="text-text-primary"></p>
                    </div>
                `;
        }

        // 获取流式响应
        function fetchStreamingResponse(message, model) {
            isStreaming = true;
            sendButton.disabled = true;
            sendButton.classList.add('opacity-50', 'cursor-not-allowed');

            const apiUrl = `http://localhost:8090/api/v1/ollama/generate_stream?model=${encodeURIComponent(model)}&message=${encodeURIComponent(message)}`;

            // 清空之前的事件源
            if (eventSource) {
                eventSource.close();
            }

            try {
                eventSource = new EventSource(apiUrl);

                let fullResponse = '';

                eventSource.onmessage = (event) => {
                    if (!event.data || event.data === '[DONE]') {
                        return;
                    }

                    try {
                        const data = JSON.parse(event.data);
                        const content = data?.result?.output?.content || '';

                        if (content) {
                            fullResponse += content;

                            // 如果AI消息元素还未添加到DOM中
                            if (!currentAiMessageElement.parentNode) {
                                // 移除"正在输入"状态
                                const typingElement = document.getElementById('ai-typing');
                                if (typingElement) {
                                    typingElement.remove();
                                }

                                // 添加AI消息元素
                                chatContainer.appendChild(currentAiMessageElement);

                                // 淡入动画
                                setTimeout(() => {
                                    currentAiMessageElement.classList.remove('opacity-0');
                                }, 10);
                            }

                            // 更新AI响应
                            const messageId = currentAiMessageElement.id;
                            const responseElement = document.getElementById(`ai-response-${messageId}`);
                            if (responseElement) {
                                responseElement.textContent = fullResponse;
                            }

                            scrollToBottom();
                        }

                        // 检查是否结束
                        const finishReason = data?.result?.metadata?.finishReason;
                        if (finishReason === 'STOP') {
                            eventSource.close();
                            addMessageToChat('assistant', fullResponse);
                            resetChatUI();
                        }
                    } catch (error) {
                        console.error('解析响应失败:', error);
                    }
                };

                eventSource.onerror = (error) => {
                    console.error('EventSource failed:', error);
                    eventSource.close();

                    // 显示错误消息
                    if (currentAiMessageElement && !currentAiMessageElement.parentNode) {
                        const typingElement = document.getElementById('ai-typing');
                        if (typingElement) {
                            typingElement.remove();
                        }

                        const messageId = currentAiMessageElement.id;
                        const responseElement = document.getElementById(`ai-response-${messageId}`);
                        if (responseElement) {
                            responseElement.textContent = '抱歉，请求处理出错，请重试。';
                        }

                        chatContainer.appendChild(currentAiMessageElement);
                        currentAiMessageElement.classList.remove('opacity-0');
                    }

                    resetChatUI();
                };

                eventSource.onopen = () => {
                    console.log('EventSource连接已建立');
                };
            } catch (error) {
                console.error('创建EventSource失败:', error);

                // 显示错误消息
                const typingElement = document.getElementById('ai-typing');
                if (typingElement) {
                    typingElement.remove();
                }

                const messageId = currentAiMessageElement.id;
                const responseElement = document.getElementById(`ai-response-${messageId}`);
                if (responseElement) {
                    responseElement.textContent = '抱歉，无法连接到服务器，请检查网络连接。';
                }

                chatContainer.appendChild(currentAiMessageElement);
                currentAiMessageElement.classList.remove('opacity-0');

                resetChatUI();
            }
        }

        // 重置聊天UI状态
        function resetChatUI() {
            isStreaming = false;
            sendButton.disabled = false;
            sendButton.classList.remove('opacity-50', 'cursor-not-allowed');
            eventSource = null;
            scrollToBottom();
        }

        // 滚动到底部
        function scrollToBottom() {
            chatContainer.scrollTop = chatContainer.scrollHeight;
        }

        // HTML转义
        function escapeHtml(text) {
            return text
                .replace(/&/g, '&amp;')
                .replace(/</g, '&lt;')
                .replace(/>/g, '&gt;')
                .replace(/"/g, '&quot;')
                .replace(/'/g, '&#039;');
        }

        // 渲染聊天列表
        function renderChatList() {
            chatList.innerHTML = '';

            chats.forEach(chat => {
                const chatItem = document.createElement('div');
                chatItem.className = `chat-item cursor-pointer p-3 rounded-lg mb-1 flex items-center justify-between ${chat.id === currentChatId ? 'chat-active' : 'chat-hover'}`;
                chatItem.dataset.id = chat.id;

                chatItem.innerHTML = `
                        <div class="flex items-center gap-2">
                            <i class="fa fa-comment-dots text-primary"></i>
                            <span class="truncate">${chat.title}</span>
                        </div>
                        <div class="flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
                            <button class="edit-chat-btn p-1 text-text-tertiary hover:text-primary">
                                <i class="fa fa-pencil"></i>
                            </button>
                            <button class="delete-chat-btn p-1 text-text-tertiary hover:text-red-500">
                                <i class="fa fa-trash"></i>
                            </button>
                        </div>
                    `;

                // 点击切换聊天
                chatItem.addEventListener('click', (e) => {
                    if (!e.target.closest('button')) {
                        currentChatId = chat.id;
                        renderChatList();
                        updateCurrentChatTitle();
                        loadChatMessages();
                    }
                });

                // 编辑聊天
                chatItem.querySelector('.edit-chat-btn').addEventListener('click', (e) => {
                    e.stopPropagation();
                    editingChatId = chat.id;
                    renameInput.value = chat.title;
                    renameModal.classList.remove('hidden');
                    renameInput.focus();
                });

                // 删除聊天
                chatItem.querySelector('.delete-chat-btn').addEventListener('click', (e) => {
                    e.stopPropagation();
                    if (confirm(`确定要删除 "${chat.title}" 吗？`)) {
                        const index = chats.findIndex(c => c.id === chat.id);
                        if (index !== -1) {
                            chats.splice(index, 1);

                            // 如果删除的是当前聊天，切换到第一个聊天或创建新聊天
                            if (chat.id === currentChatId) {
                                if (chats.length > 0) {
                                    currentChatId = chats[0].id;
                                } else {
                                    const newChatId = `chat-${Date.now()}`;
                                    const newChat = {
                                        id: newChatId,
                                        title: `新聊天 1`,
                                        messages: []
                                    };
                                    chats.push(newChat);
                                    currentChatId = newChatId;
                                }

                                updateCurrentChatTitle();
                                loadChatMessages();
                            }

                            renderChatList();
                        }
                    }
                });

                chatList.appendChild(chatItem);
            });
        }

        // 更新当前聊天标题
        function updateCurrentChatTitle() {
            const chat = chats.find(c => c.id === currentChatId);
            if (chat) {
                currentChatTitle.textContent = chat.title;
            }
        }

        // 清空聊天容器
        function clearChatContainer() {
            chatContainer.innerHTML = '';
        }

        // 加载聊天消息
        function loadChatMessages() {
            clearChatContainer();

            const chat = chats.find(c => c.id === currentChatId);
            if (chat && chat.messages.length > 0) {
                chat.messages.forEach(message => {
                    if (message.role === 'user') {
                        appendUserMessage(message.content);
                    } else if (message.role === 'assistant') {
                        // 模拟AI回复，这里只是显示完整内容，没有流式效果
                        const aiMessageHtml = `
                                <div class="flex items-start mb-6 animate-fade-in">
                                    <div class="flex-shrink-0 mr-3">
                                        <div class="h-10 w-10 rounded-full bg-primary flex items-center justify-center text-white">
                                            <i class="fa fa-robot"></i>
                                        </div>
                                    </div>
                                    <div class="bg-white p-4 rounded-lg rounded-tl-none max-w-[90%] shadow-sm">
                                        <p class="text-text-primary">${escapeHtml(message.content)}</p>
                                    </div>
                                </div>
                            `;

                        chatContainer.insertAdjacentHTML('beforeend', aiMessageHtml);
                    }
                });

                scrollToBottom();
            } else {
                // 添加欢迎消息
                const welcomeHtml = `
                        <div class="flex items-start mb-6 animate-fade-in">
                            <div class="flex-shrink-0 mr-3">
                                <div class="h-10 w-10 rounded-full bg-primary flex items-center justify-center text-white">
                                    <i class="fa fa-robot"></i>
                                </div>
                            </div>
                            <div class="bg-white p-4 rounded-lg rounded-tl-none max-w-[90%] shadow-sm">
                                <p class="text-text-primary">你好！我是AI助手，有什么可以帮助你的吗？</p>
                            </div>
                        </div>
                    `;

                chatContainer.insertAdjacentHTML('beforeend', welcomeHtml);
            }
        }

        // 添加消息到当前聊天
        function addMessageToChat(role, content) {
            const chat = chats.find(c => c.id === currentChatId);
            if (chat) {
                chat.messages.push({
                    role,
                    content
                });
            }
        }
    });
</script>
</body>
</html>
    